package com.dave.gd.core.context;

import java.io.IOException;
import java.io.Serializable;
import java.util.concurrent.ConcurrentMap;

import com.dave.gd.common.exception.RtManagerException;
import com.dave.gd.common.log.ILogger;
import com.dave.gd.common.log.LoggerFactory;
import com.dave.gd.common.util.NumberUtils;
import com.dave.gd.common.util.StringUtils;
import com.dave.gd.common.util.serial.SerializationUtils;
import com.dave.gd.common.util.spring.ApplicationContextUtil;
import com.dave.gd.core.base.entity.ISysClass;
import com.dave.gd.core.base.entity.impl.AbstractBaseEntity;
import com.dave.gd.core.cache.CacheEnttManager;
import com.dave.gd.core.contants.BaseUnitConstants;
import com.dave.gd.core.util.MetaProvider;

public class CacheContext {
    
    private static final ILogger LOG = LoggerFactory.getLogger(CacheContext.class);
    
    private static CacheEnttManager cacheEnttManager = (CacheEnttManager) ApplicationContextUtil
        .getBean("cacheEnttManager");
    
    /**
     * 
     * 方法功能:
     *  根据配置放到不同的缓存.
     * @param enttName
     * @param id
     * @param entity
     * @param isRemove
     * @author: linzq
     * @修改记录： 
     * ==============================================================<br>
     * 日期:2014-12-6 linzq 创建方法，并实现其功能
     * ==============================================================<br>
     */
    private static void setEnttToCache(String enttName, Serializable id, Object entity,
        boolean isRemove) {
        
        ISysClass sysClass = null;
        if (entity != null && entity instanceof AbstractBaseEntity) {
            if (entity instanceof ISysClass) {
                sysClass = (ISysClass) entity;
            } else if (((AbstractBaseEntity) entity).getModelClass() != null) {
                sysClass = ((AbstractBaseEntity) entity).getModelClass();
            }
        } else {
            String entityname = StringUtils.substringAfterLast(enttName, ".");
            sysClass = MetaProvider.getEntityByName(entityname);
        }
        
        try {
            if (sysClass != null) {
                //对象拷贝缓存
                if (BaseUnitConstants.CACHE_ENTT_BACKUP.equals(sysClass.getIsSessionCache())) {
                    setEnttToThreadCache(enttName, id, entity, isRemove);
                } else if (BaseUnitConstants.CACHE_GLOBAL.equals(sysClass.getIsSessionCache())) {//全局缓存
                    if (isRemove) {
                        removeEnttFromGlobalCache(enttName, id, entity);
                    } else {
                        setEnttToGlobalCache(enttName, id,
                            NumberUtils.nullToZero(sysClass.getTtl()), entity);
                    }
                }
            }
        } catch (Exception e) {
            LOG.error("放入缓存失败", e);
        }
    }
    
    /**
     * 
     * 方法功能:
     *  从缓存取.
     * @param enttName
     * @param id
     * @return
     * @author: linzq
     * @修改记录： 
     * ==============================================================<br>
     * 日期:2014-12-6 linzq 创建方法，并实现其功能
     * ==============================================================<br>
     */
    public static Object getEnttFromCache(String enttName, Serializable id) {
        ISysClass sysClass = null;
        String entityname = StringUtils.substringAfterLast(enttName, ".");
        sysClass = MetaProvider.getEntityByName(entityname);
        
        try {
            if (sysClass != null) {
                //对象拷贝缓存
                if (BaseUnitConstants.CACHE_ENTT_BACKUP.equals(sysClass.getIsSessionCache())) {
                    return getEnttFromThreadCache(enttName, id);
                } else if (BaseUnitConstants.CACHE_GLOBAL.equals(sysClass.getIsSessionCache())) {//全局缓存
                    return getEnttFromGlobalCache(enttName, id);
                }
            }
        } catch (Exception e) {
            LOG.error("获取对象失败", e);
        }
        
        return null;
        
    }
    
    /**
     * 
     * 方法功能:
     *  根据配置从缓存中移除.
     * @param enttName
     * @param id
     * @param entity
     * @author: linzq
     * @修改记录： 
     * ==============================================================<br>
     * 日期:2014-12-6 linzq 创建方法，并实现其功能
     * ==============================================================<br>
     */
    public static void removeEnttFromCache(String enttName, Serializable id, Object entity) {
        try {
            setEnttToCache(enttName, id, entity, true);
        } catch (Exception e) {
            LOG.error("获取对象失败", e);
        }
    }
    
    /**
     * 
     * 方法功能:
     *  根据配置，放入不同的缓存.
     * @param enttName
     * @param id
     * @param entity
     * @author: linzq
     * @修改记录： 
     * ==============================================================<br>
     * 日期:2014-12-6 linzq 创建方法，并实现其功能
     * ==============================================================<br>
     */
    public static void setEnttToCache(String enttName, Serializable id, AbstractBaseEntity entity) {
        setEnttToCache(enttName, id, entity, false);
    }
    
    private static String getCacheKey(String enttName, Serializable id) {
        return enttName + BaseUnitConstants.CACHE_TAG_SPLIT + id;
    }
    
    private static Object copyEntity(Object source) {
        Object dest = null;
        try {
            dest = (Object) SerializationUtils.deserialize(SerializationUtils.serialize(source));
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return dest;
    }
    
    /**
     * 
     * 方法功能:
     *  根据配置，操作线程级缓存.
     * @param enttName
     * @param id
     * @param entity
     * @param isRemove
     * @author: linzq
     * @修改记录： 
     * ==============================================================<br>
     * 日期:2014-12-6 linzq 创建方法，并实现其功能
     * ==============================================================<br>
     */
    private static void setEnttToThreadCache(String enttName, Serializable id, Object entity,
        boolean isRemove) {
        
        try {
            if (entity != null) {
                ConcurrentMap<String, Object> map = SessionContext.getEnttBackupCache();
                if (map != null) {
                    String key = getCacheKey(enttName, id);
                    if (!map.containsKey(key)) {
                        Object dest = copyEntity(entity);
                        if (dest == null) {
                            throw new RtManagerException("对象复制失败");
                        }
                        map.putIfAbsent(getCacheKey(enttName, id), dest);
                    }
                }
            }
        } catch (Exception e) {
            LOG.error("放入缓存失败", e);
        }
    }
    
    /**
     * 
     * 方法功能:
     *  从线程缓存中取数据.
     * @param enttName
     * @param id
     * @return
     * @author: linzq
     * @修改记录： 
     * ==============================================================<br>
     * 日期:2014-12-6 linzq 创建方法，并实现其功能
     * ==============================================================<br>
     */
    public static Object getEnttFromThreadCache(String enttName, Serializable id) {
        try {
            ConcurrentMap<String, Object> map = SessionContext.getEnttBackupCache();
            if (map != null) {
                return map.get(getCacheKey(enttName, id));
            }
        } catch (Exception e) {
            LOG.error("获取对象失败", e);
        }
        
        return null;
        
    }
    
    /**
     * 
     * 方法功能:
     *  从线程缓存中移除.
     * @param enttName
     * @param id
     * @param entity
     * @author: linzq
     * @修改记录： 
     * ==============================================================<br>
     * 日期:2014-12-6 linzq 创建方法，并实现其功能
     * ==============================================================<br>
     */
    public static void removeEnttFromThreadCache(String enttName, Serializable id, Object entity) {
        try {
            setEnttToThreadCache(enttName, id, entity, true);
        } catch (Exception e) {
            LOG.error("获取对象失败", e);
        }
    }
    
    /**
     * 
     * 方法功能:
     *  对象放入线程缓存.
     * @param enttName
     * @param id
     * @param entity
     * @author: linzq
     * @修改记录： 
     * ==============================================================<br>
     * 日期:2014-12-6 linzq 创建方法，并实现其功能
     * ==============================================================<br>
     */
    public static void setEnttToThreadCache(String enttName, Serializable id, Object entity) {
        setEnttToThreadCache(enttName, id, entity, false);
    }
    
    /**
     * 
     * 方法功能:
     *  根据配置，操作全局缓存.
     * @param enttName
     * @param id
     * @param entity
     * @param isRemove
     * @author: linzq
     * @修改记录： 
     * ==============================================================<br>
     * 日期:2014-12-6 linzq 创建方法，并实现其功能
     * ==============================================================<br>
     */
    private static void setEnttToGlobalCache(String enttName, Serializable id, Object entity,
        int ttl, boolean isRemove) {
        try {
            if (NumberUtils.nullToZero(ttl) <= 0) {
                cacheEnttManager.putObjectToCache(enttName, getCacheKey(enttName, id), entity,
                    true, BaseUnitConstants.CACHE_DEFAULT_TTL, isRemove);
            } else {
                cacheEnttManager.putObjectToCache(enttName, getCacheKey(enttName, id), entity,
                    true, NumberUtils.nullToZero(ttl), isRemove);
            }
        } catch (Exception e) {
            LOG.error("放入缓存失败", e);
        }
    }
    
    /**
     * 
     * 方法功能:
     *  根据配置，操作全局缓存.
     * @param enttName
     * @param id
     * @param entity
     * @param isRemove
     * @author: linzq
     * @修改记录： 
     * ==============================================================<br>
     * 日期:2014-12-6 linzq 创建方法，并实现其功能
     * ==============================================================<br>
     */
    private static void setEnttToGlobalCache(String enttName, Serializable id, Object entity,
        boolean isRemove) {
        try {
            setEnttToGlobalCache(enttName, id, entity, -1, isRemove);
        } catch (Exception e) {
            LOG.error("放入缓存失败", e);
        }
    }
    
    /**
     * 
     * 方法功能:
     *  从全局缓存中取数据.
     * @param enttName
     * @param id
     * @return
     * @author: linzq
     * @修改记录： 
     * ==============================================================<br>
     * 日期:2014-12-6 linzq 创建方法，并实现其功能
     * ==============================================================<br>
     */
    public static Object getEnttFromGlobalCache(String enttName, Serializable id) {
        try {
            Object object = cacheEnttManager.getObjectFromCache(enttName,
                getCacheKey(enttName, id), true);
            if (object != null) {
                LOG.debug("获取对象" + object);
                return object;
            }
        } catch (Exception e) {
            LOG.error("获取对象失败", e);
        }
        
        return null;
        
    }
    
    /**
     * 
     * 方法功能:
     *  从全局缓存中移除.
     * @param enttName
     * @param id
     * @param entity
     * @author: linzq
     * @修改记录： 
     * ==============================================================<br>
     * 日期:2014-12-6 linzq 创建方法，并实现其功能
     * ==============================================================<br>
     */
    public static void removeEnttFromGlobalCache(String enttName, Serializable id, Object entity) {
        try {
            setEnttToGlobalCache(enttName, id, entity, true);
        } catch (Exception e) {
            LOG.error("获取对象失败", e);
        }
    }
    
    /**
     * 
     * 方法功能:
     *  对象放入全局缓存.
     * @param enttName
     * @param id
     * @param entity
     * @author: linzq
     * @修改记录： 
     * ==============================================================<br>
     * 日期:2014-12-6 linzq 创建方法，并实现其功能
     * ==============================================================<br>
     */
    public static void setEnttToGlobalCache(String enttName, Serializable id, Object entity) {
        setEnttToGlobalCache(enttName, id, entity, -1, false);
    }
    
    /**
     * 
     * 方法功能:
     *  对象放入全局缓存.
     * @param enttName
     * @param id
     * @param entity
     * @author: linzq
     * @修改记录： 
     * ==============================================================<br>
     * 日期:2014-12-6 linzq 创建方法，并实现其功能
     * ==============================================================<br>
     */
    public static void setEnttToGlobalCache(String enttName, Serializable id, int ttl, Object entity) {
        setEnttToGlobalCache(enttName, id, entity, ttl, false);
    }
    
}
